#include "buzzer.h"
#include <stdlib.h>
#include <stdbool.h>

typedef struct {
    uint8_t level;
    uint16_t duration_ticks;
} BeepStep;

typedef struct {
    const BeepStep *steps;
    uint16_t step_count;
    bool loop;
} BeepPattern;

static const BeepStep alarm_steps[] = {
    {1, 5}, {0, 5}
};

static const BeepStep notice_steps[] = {
    {1, 100}, {0, 1}
};

static const BeepStep short_beep_steps[] = {
    {1, 10}, {0, 1}
};

static const BeepStep error_steps[] = {
    {1, 10}, {0, 10}, {1, 10}, {0, 30}
};

static const BeepPattern patterns[] = {
    [BEEP_ALARM]      = {alarm_steps,      sizeof(alarm_steps)/sizeof(BeepStep), true},
    [BEEP_NOTICE]     = {notice_steps,     sizeof(notice_steps)/sizeof(BeepStep), false},
    [BEEP_SHORT_BEEP] = {short_beep_steps, sizeof(short_beep_steps)/sizeof(BeepStep), false},
    [BEEP_ERROR]      = {error_steps,      sizeof(error_steps)/sizeof(BeepStep), true},
};

static struct {
    const BeepPattern *current_pattern;
    uint16_t current_step;
    uint16_t remaining_ticks;
    bool is_active;
} beeper;

void Buzzer_Init(void) {
//    __HAL_RCC_GPIOA_CLK_ENABLE();
//    GPIO_InitTypeDef GPIO_InitStruct = {
//        .Pin = GPIO_PIN_15,
//        .Mode = GPIO_MODE_OUTPUT_PP,
//        .Pull = GPIO_NOPULL,
//        .Speed = GPIO_SPEED_FREQ_LOW
//    };
//    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
//    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
}

void Buzzer_StartBeep(BeepType type) {
    if (type >= BEEP_TYPE_COUNT) return;
    
    beeper.current_pattern = &patterns[type];
    beeper.current_step = 0;
    beeper.remaining_ticks = beeper.current_pattern->steps[0].duration_ticks;
    beeper.is_active = true;
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, beeper.current_pattern->steps[0].level ? GPIO_PIN_SET : GPIO_PIN_RESET);
}

void Buzzer_StopBeep(void) {
    beeper.is_active = false;
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
}

void Buzzer_Update10ms(void) {
    if (!beeper.is_active) return;

    if (--beeper.remaining_ticks == 0) {
        beeper.current_step++;
        
        if (beeper.current_step >= beeper.current_pattern->step_count) {
            if (beeper.current_pattern->loop) {
                beeper.current_step = 0;
            } else {
                Buzzer_StopBeep();
                return;
            }
        }
        
        BeepStep next_step = beeper.current_pattern->steps[beeper.current_step];
        beeper.remaining_ticks = next_step.duration_ticks;
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, next_step.level ? GPIO_PIN_SET : GPIO_PIN_RESET);
    }
}